rxjava+retrofit+okhttp+mvp 简单实践
一个关于rxjava+retrofit+okhttp+mvp的封装实现,一步一步教会你如何如何使用RROM的结合,适合于初学者。
该篇是来自于Kimi的投稿,Kimi是一个多年经验的老司机,刚进一家公司就要进行代码重构,rxjava+retrofit+okhttp+mvp将会是一个很好的选择。
Kimi的博客地址:
http://www.itkimi.com/showArticle.jsp?id=7
Rxjava,Retrofit,Okhttp,MVP,这些关键字都是去年比较流行的,随便一个技术论坛或者技术博客,都可以看到,如果你或者他,还对这些关键词感觉到陌生的话,恭喜你,你和我一样了,OUT了,o(∩_∩)o 。
还有,学习新东西一定不要着急,一步一步来,看一遍不明白,那么回过头来看第二遍,第三遍…..看的多了,熟悉了,那么就会用了,如果有上进心的话,可以研究源码,想想具体实现原理等。
水平线~~~~
Rxjava知识,推荐扔物线的博客,地址:http://gank.io/post/560e15be2dca930e00da1083
我想说的是,这篇博客我看了不下5遍,刚开始很容易弄晕,后来看着看着就明白了。
Retrofit知识,直接看官方文档,地址:
http://square.github.io/retrofit/
Okhttp知识,也直接看官方文档,地址:
http://square.github.io/okhttp/
MVP 相关,这里推荐先看下谷歌的官方demo,地址:https://github.com/googlesamples/android-architecture
以上截图是官方的demo,MVP,MVVM等都在上面,值得参考。
看完官方的在推荐看下这个博客,地址:
http://www.jianshu.com/p/ac51c9b88af3
或者 直接拿Github上现成的 MVPArms,地址:
https://github.com/JessYanCoding/MVPArms/wiki
好了,我知道的就这么多了~~~~
现在来看下我项目中自己的实践封装,我尽量写详细点,有问题或者觉得不妥的地方都可以给我提意见,互相帮助,才是学习的进步嘛。
先看下项目的配置文件:
红色框圈中的部分都是依赖,这点AS确实很方便,想想如果换成Eclipse的话,该有多麻烦啊。事实上,现在AS已经慢慢的成为主流了,虽然我现在看的是14年的项目,它是EC结构的,汗。
依赖添加完成后,再来看下项目的包结构:
1.net里放的都是网络请求相关,以及封装okhttp下载监听,上传监听的实现。
2.mvp自然就是View,Presenter,Mode了。
3.util 工具类。
4.view 自定义的view。
5.common 相关通用的东西。
一、网络请求的封装:
网络请求主要看ApiServer.java,RetrofitManager.java,StringObserver.java和BaseObserver.java这四个类即可。
1.ApiServer.java :
public interface ApiServer {
@GET("{url}")
Observable<String> get(@Path("url") String url,@QueryMap Map<String, String> maps);
@FormUrlEncoded
@POST("{url}")
Observable<String> post( @Path("url") String url, @FieldMap Map<String, String> maps);
@POST("{url}")
Observable<String> post( @Path("url") String url,@Body RequestBody body); @Multipart
@POST("{url}")
Observable<String> uploadFile( @Path("url") String url, @Part("description") RequestBody description,
@Part MultipartBody.Part file);
@Multipart
@POST("{url}")
Observable<String> uploadFile( @Path("url") String url, @PartMap Map<String, RequestBody> map);
@GET
Call<ResponseBody> downloadFile(@Url String fileUrl);
}
Retrofit的写法和官方的没什么区别,唯一的区别就是url没有写死。定义了几个常用的get,post(key-value以及json),上传文件,下载文件等。
2.RetrofitManager.java
private RetrofitManager() {
mRetrofit = new Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) //.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.baseUrl(Constant.Base_Url)
.client(getOkhttpClient())
.build();
apiServer = mRetrofit.create(ApiServer.class);
}
private OkHttpClient getOkhttpClient() {
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() { @Override
public void log(String message) {
NetLog.d("", message);
}
});
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
mOkhttp = new OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor)
.addInterceptor(new PublicParamsInterceptor())
.connectTimeout(CONNEC_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.retryOnConnectionFailure(false)
.connectionPool(new ConnectionPool())
.build();
return mOkhttp;
}
public static RetrofitManager getInstance() {
if (mInstance == null) {
synchronized (RetrofitManager.class) {
if (mInstance == null) {
mInstance = new RetrofitManager();
}
}
} return mInstance;
}
public ApiServer getApiServer() {
return apiServer;
}
//使用方法
//单利设计模式,因为整个项目中共用同一个网络请求即可。这些天看的14年的项目,想哭的心都有那~~~
mRetrofit = new Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) //.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.baseUrl(Constant.Base_Url)
.client(getOkhttpClient())
.build();
看到添加了两个converter了吗,其实是这样的,本来想直接封装成BaseBean的,但是发现后台返回的数据根本就没统一,一下data,一下orders的,唯一统一的就一个resultCode字段,“SUCCESS” 代表成功,否则失败。最可气,最可气的是接口文档都没有,接下来这几天又要自己去整理下接口文档了,香菇。
这也是为什么会有StringObserver.java和BaseObserver.java两个类的出现了,可能也有更好的解决办法,这里只能选择String让调用者自己去解析了。
mOkhttp = new OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor)
.addInterceptor(new PublicParamsInterceptor())
.connectTimeout(CONNEC_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.retryOnConnectionFailure(false)
.connectionPool(new ConnectionPool())
.build();
addInterceptor(httpLoggingInterceptor) 添加日志打印的拦截器
addInterceptor(new PublicParamsInterceptor())添加公共参数的拦截器
看下get,post(key—vaule,json),上传,下载
/**
* get请求 接口不统一 只能一个一个去解析了 *
* @param url
* @param params
* @param observer
*/
public void get(String url, Map<String, String> params, Observer observer) {
getApiServer().get(url, params).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(observer);
}
/**
* post key-value 请求 *
* @param url
* @param params
* @param observer
*/
public void post(String url, Map<String, String> params, Observer observer) {
getApiServer().post(url, params).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(observer);
}
/**
* post json请求 *
* @param url
* @param json
* @param observer
*/
public void json(String url, String json, Observer observer) {
RequestBody body = RequestBody.create(MediaType.parse("application/json;charset=utf-8"), json);
getApiServer().post(url, body).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(observer);
}
/**
* 上传单个文件 *
* @param url
* @param file
* @param progress
*/
public void uploadFile(String url, File file, @NonNull final ProgressListener progress, Observer observer) {
OkHttpClient.Builder newBuilder = mOkhttp.newBuilder();
List<Interceptor> networkInterceptors = newBuilder.networkInterceptors();
Interceptor it = new Interceptor() { @Override
public Response intercept(Chain arg0) throws IOException {
Request request = arg0.request();
Request build = request.newBuilder().method(request.method(), new ProgressRequestBody(request.body(), progress)).build();
return arg0.proceed(build);
}
};
networkInterceptors.add(it);
ApiServer apiServer = mRetrofit.newBuilder().client(newBuilder.build()).build().create(ApiServer.class);
RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part part = MultipartBody.Part.createFormData("image", file.getName(), body);
RequestBody des = RequestBody.create(MediaType.parse("multipart/form-data"), "des");
apiServer.uploadFile(url, des, part).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(observer);
}
/**
* 下载文件 *
* @param url
* @param listener
*/
public void downLoadFile(String url, @NonNull final ProgressListener listener, @NonNull final retrofit2.Callback<ResponseBody> call) {
OkHttpClient.Builder newBuilder = mOkhttp.newBuilder();
List<Interceptor> networkInterceptors = newBuilder.networkInterceptors();
Interceptor it = new Interceptor() { @Override
public Response intercept(Chain arg0) throws IOException {
Response proceed = arg0.proceed(arg0.request());
ProgressResponseBody body = new ProgressResponseBody(proceed.body(), listener);
return proceed.newBuilder().body(body).build();
}
};
networkInterceptors.add(it);
Retrofit build = mRetrofit.newBuilder().client(newBuilder.build()).build();
ApiServer apiServer = build.create(ApiServer.class);
apiServer.downloadFile(url).enqueue(call);
}
使用者直接调用即可,可能封装的不是很好,自己也是第一次使用这些框架的,有问题麻烦提出。
3.StringObserver.java
public abstract class StringObserver implements Observer<String> {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
try {
onSuccess(s);
}catch (Exception e){
e.printStackTrace();
ToastUtils.showMsg("发生错误,请重试!");
onComplete();
}
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
onFaild(e);
onComplete();
}
protected abstract void onSuccess(String json) throws Exception;protected abstract void onFaild(Throwable e);
}
4.BaseObserver.java
public abstract class BaseObserver implements Observer<BaseBean>{
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(BaseBean baseBean) {
try{
if(baseBean != null && baseBean.isSuccess()){
onSuccess(baseBean);
}else{
baseBean.showErrorMsg();
}
}catch (Exception e){
e.printStackTrace();
ToastUtils.showMsg("发生错误,请重试!");
onComplete();
}
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
onFail();
onComplete();
}
@Override
public void onComplete() {
}
public abstract void onSuccess(BaseBean baseBean);
public abstract void onFail();
}
回调的简单封装,如果接口文档规范的话,使用起来会更加方便。
二、MVP:
看过谷歌官方demo的话,会发现有一个contract把view和presenter关联起来,所以这里也遵循了谷歌的做法,每个界面对应了3个类,分别是presenter,constract,task。
这应该是最基本的一个mvp Demo了,面对这么多的接口,刚开始我也无从去下手,但我们应该学会去接收新鲜事物,不断去学习,去进步。
这里强烈推荐:传统MVP用在项目中是真的方便还是累赘?
地址 http://www.jianshu.com/p/ac51c9b88af3
项目链接地址:
Github地址:
https://github.com/andmizi/Rxjava-Retrofit-Okhttp-Mvp
博客链接地址:
Kimi的博客地址:
http://www.itkimi.com/showArticle.jsp?id=7